package com.zpz.framework.zpzoauth.config.oauth.authorization;

import com.zpz.framework.zpzoauth.common.utils.ZpzOauthRequestUtil;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultMsg;
import com.zpz.framework.zpzoauth.pojo.po.OauthClientDetails;
import com.zpz.framework.zpzoauth.pojo.vo.Authorize;
import com.zpz.framework.zpzoauth.pojo.vo.UserAuthenticationVo;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.ZpzOauthIntegrationAuthentication;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.ZpzOauthIntegrationAuthenticationContext;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.ZpzOauthIntegrationAuthenticator;
import com.zpz.framework.zpzoauth.service.ZpzOauthFrameUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
 * @author zhangpanzhi
 * @time 2019-07-09
 * @description 未经本人允许请勿随便改动，尊重劳动
 * */
@Service
public class ZpzOauthIntegrationUserDetailsService implements UserDetailsService {

    @Autowired
    private ZpzOauthFrameUserService zpzOauthFrameUserService ;
    private List<ZpzOauthIntegrationAuthenticator> authenticators;
    @Resource
    private ZpzOauthRequestUtil zpzOauthRequestUtil;
    @Autowired(required = false)
    public void setIntegrationAuthenticators(List<ZpzOauthIntegrationAuthenticator> authenticators) {
        this.authenticators = authenticators;
    }

    @Override
    public ZpzOauthUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ZpzOauthIntegrationAuthentication integrationAuthentication = ZpzOauthIntegrationAuthenticationContext.get();
        //判断是否是集成登录
        if (integrationAuthentication == null) {
            integrationAuthentication = new ZpzOauthIntegrationAuthentication();
        }
        integrationAuthentication.setUsername(username);
        UserAuthenticationVo sysUserAuthentication = this.authenticate(integrationAuthentication);

        if(sysUserAuthentication == null){
            throw new UsernameNotFoundException("账号或密码错误");
        }

        ZpzOauthUserDetails user = new ZpzOauthUserDetails();
        BeanUtils.copyProperties(sysUserAuthentication, user);
        this.setAuthorize(user,integrationAuthentication.getClientId());
        return user;

    }

    /**
     * 设置授权信息
     * @param user
     */
    public void setAuthorize(ZpzOauthUserDetails user, String clientId) {
        OauthClientDetails client= zpzOauthRequestUtil.getClient(clientId);
        if (client==null){
            throw new OAuth2Exception("无效的客户端");
        }
        Integer accessType= client.getAccessType();
        if (accessType==null){
            throw new OAuth2Exception("没有配置客户端限定用户权限类型");
        }
        // 客户端权限类型$0URBAC（基于用户角色）类型$1CRBAC（基于客户端角色）$2（基于部门）
        if (accessType==1){
            String authorities = client.getAuthorities();
            String[] accs = authorities.split(",");
            List<String> roles = Arrays.asList(accs);
            user.setRoles(roles);
        } else if (accessType==0){
            ZpzOauthResultMsg<Authorize> authorize = zpzOauthFrameUserService.getAuthorize(user.getUserCode(),clientId);
            user.setRoles(authorize.getData().getRoles());
        } else if (accessType==2){
            ZpzOauthResultMsg<Authorize> authorize = zpzOauthFrameUserService.getAuthorizeDepartment(user.getUserCode());
            user.setRoles(authorize.getData().getRoles());
        }
    }

    private UserAuthenticationVo authenticate(ZpzOauthIntegrationAuthentication integrationAuthentication) {
        if (this.authenticators != null) {
            for (ZpzOauthIntegrationAuthenticator authenticator : authenticators) {
                if (authenticator.support(integrationAuthentication)) {
                    return authenticator.authenticate(integrationAuthentication);
                }
            }
        }
        return null;
    }
}
